<?php

require_once dirname(__FILE__) . '/../tokens.php';
require_once 'js_token.class.php';

class JS_TokenManager {
	
	protected $tokens;
	protected $count;
	protected $skip;
	protected $cur;
	
	const T_SKIP = "\n\t\r";
	const T_DOUBLE_OP = "+-=<>";
	
	public static function &tokenize(&$str) {
		global $TOKENS, $DATA_TYPES;
		
		$i=0; $count=0; $head = null; $token_list=null; $token=''; $scope='ALL';
		do {
			$ch = $str[$i++];
			switch ($ch) {
				//case "\n":
				case " ":
				case "\r":
				case "\t":
					self::consumeTokens($str, $i);
					break;
				default:
					$token .= $ch;
					switch ($ch) {
						case '"':
						case '\'':
						// we have a string, so let's grab it
						preg_match('/' . $ch . '((\\\\.|[^' . $ch . '])*)' . $ch . '/', substr($str, $i - 1), $match);
						$token = $match[0];
						$i += strlen($token) - 1;
						if (!$token_list) {
							$head = $token_list = new JS_Token('STR_LITERAL', $token);
						}
						else {
							$token_list->setNext(new JS_Token('STR_LITERAL', $token));
							$token_list = $token_list->getNext();
						}
						++$count;
						$token = '';
						break;
					}
					
					// check if we have a double operator
					while ($ch == $str[$i] && strchr(self::T_DOUBLE_OP,$ch)) {
						$ch = $str[$i++];
						$token .= $ch;
					}
					// check if we have a token
					if (($key = array_search($token, $TOKENS)) !== FALSE) {
						if (!$token_list) {
							$head = $token_list = new JS_Token($key, $token);
						}
						else {
							$token_list->setNext(new JS_Token($key, $token));
							$token_list = $token_list->getNext();
						}
						++$count;
					}
					else {
						// collect more chars
						while (ctype_alnum($ch = $str[$i])) {
							$token .= $ch;
							++$i;
						}
						// check if we have a token
						if (($key = array_search($token, $TOKENS)) === FALSE) {
							if (ctype_digit($token)) {
								$key = 'INT_LITERAL';
							}
							else {
								// check if it's a data type
								if (($key = array_search($token, $DATA_TYPES)) === FALSE) {
									// label it as an identifier
									$key = 'ID';
								}
								else {
									$key = strtoupper($DATA_TYPES[$key]);
								}
							}
						}
						// add whatever we end up with
						if ($token != '') {
							if (!$token_list) {
								$head = $token_list = new JS_Token($key, $token);
							}
							else {
								$token_list->setNext(new JS_Token($key, $token));
								$token_list = $token_list->getNext();
							}
							++$count;
						}
					}
					$token = '';
					break;
			}
		} while (isset($str[$i]));
		
	//	_d($head);
		
		return $head;
	}
	
	public static function consumeTokens(&$str, &$i, $skip=self::T_SKIP) {
		while (isset($str[$i]) && strchr($skip, $str[$i])) ++$i;
	}
	
}

?>